#!/usr/bin/env python
# -*-coding:utf-8 -*-

__all__ = ['CompositeTask', 'add', 'addRight', 'addLeft', 'isEmpty', '__getitem__', 
           'setFirstTaskScheduled', 'setFirstTaskCompleted', 'isFirstTaskScheduled', 
           'getNextUncompletedTask', 'getPriority', 'isAssigned', 
           '__lt__', '__gt__', '__le__', '__ge__', '__eq__', '__ne__', 
           'assignTo', 'getAssignedRobotController']

class CompositeTask(object):
    #__slots__= ['_tasks', '_assigned', '_assigned_robot_controller']
                
    def __init__(self, create_time, creator='user'):
        """
        创建一个复合任务（多个简单任务组成的一个任务，每个简单任务可以被单独调度，但是整个复合任务统一分发）。
        :param create_time: 该复合任务的创建时间。
        :param creator: 该复合任务由谁创建。可以设置的值为'user'或者'system'，即由用户发起或由系统发起。
        """
        self._create_time = create_time
        self._creator = creator
        self._tasks = []
        self._assigned = False
        self._assigned_robot_controller = None
    
    def getCreateTime(self):
        return self._create_time
        
    def getCreator(self):
        return self._creator
        
    def add(self, task):
        """
        在复合任务中添加一个简单任务，添加到最后。本方法与addRight作用相同，函数名更直观，方便调用。
        :param task: 添加的简单任务（Task对象）。
        """
        self.addRight(task)
        
    def addRight(self, task):
        """
        在复合任务中添加一个简单任务，添加到最后。
        :param task: 添加的简单任务（Task对象）。
        """
        if len(self._tasks) == 0:
            self._tasks.append(task)
        elif task.getSrc() == None:
            task.setSrc(self._tasks[-1].getDst())
            self._tasks.append(task)
        elif task.getSrc() == self._tasks[-1].getDst():
            self._tasks.append(task)
        else:
            raise ValueError("The source node of the added task is not compatible with the other tasks!")
        
    def addLeft(self, task):
        """
        在复合任务中添加一个简单任务，添加到最前。
        :param task: 添加的简单任务（Task对象）。
        """
        #print('task dst', task.getDst())
        #print('self task[0] src', self._tasks[0].getSrc())
        if len(self._tasks) == 0 or task.getDst() == self._tasks[0].getSrc():
            self._tasks.insert(0, task)
        else:
            raise ValueError("The destination node of the added task is not compatible with the other tasks!")
            
    def isEmpty(self):
        """
        判断本复合任务是否为空（不包含任何简单任务）。
        :return: True或者False。True为空。
        """
        return len(self._tasks) == 0
            
    def __getitem__(self, idx):
        """
        获取下标为idx的简单任务。
        :return: 下标为idx的简单任务（Task对象）。
        """
        if idx < 0 or idx > len(self._tasks):
            raise IndexError("Index out of range!")
        else:
            return self._tasks[idx]

    def setFirstTaskProcessing(self):
        """
        将本复合任务中第一个简单任务的状态设置为正在处理。
        """
        if len(self._tasks) == 0:
            raise ValueError("No task in the CompositeTask!")
        else:
            self._tasks[0].setProcessing()
            
    def setFirstTaskPending(self):
        """
        将本复合任务中第一个简单任务的状态设置为挂起。
        """
        if len(self._tasks) == 0:
            raise ValueError("No task in the CompositeTask!")
        else:
            self._tasks[0].setPending()

    def setFirstTaskCompleted(self):
        """
        将本复合任务中第一个简单任务的状态设置为已完成。该方法会从复合任务中删除第一个简单任务。
        """
        if len(self._tasks) == 0:
            raise ValueError("No task in the CompositeTask!")
        else:
            self._tasks[0].setCompleted()
            del self._tasks[0]
            
    #def isFirstTaskNotScheduled(self):
    #    """
    #    判断本复合任务中第一个简单任务是否为空（不包含任何简单任务）。
    #    :return: True或者False。True为第一个任务已调度。
    #    """
    #    if len(self._tasks) == 0:
    #        raise ValueError("No task in the CompositeTask!")
    #    else:
    #        return self._tasks[0].isNotScheduled()
    
    def isFirstTaskUnderProcessing(self):
        if len(self._tasks) == 0:
            raise ValueError("No task in the CompositeTask!")
        else:
            return self._tasks[0].isProcessing()
    
    def getNextUncompletedTask(self):
        """
        获取下一个未完成的简单任务。
        :return: 下一个未完成的简单任务。因为已完成的简单任务都将被删除（见setFirstTaskCompleted），
                 因此实际返回的是第一个简单任务。
        """
        if len(self._tasks) == 0:
            return None
        else:
            return self._tasks[0]
            
    def getLastUncompletedTask(self):
        """
        获取最后一个未完成的简单任务。
        :return: 最后一个未完成的简单任务。
        """
        if len(self._tasks) == 0:
            return None
        else:
            return self._tasks[-1]
        
    def getPriority(self):
        """
        获取本复合任务的优先级。复合任务中的每一个简单任务都可以拥有独立的优先级，
        因为第一个任务是最先被分发和调度的，所以本方法返回第一个任务的优先级。
        """
        return self._tasks[0].getPriority()
        
    def isAssigned(self):
        """
        判断本复合任务是否已经被分发给某个机器人控制器。
        :return: 如果本任务已经被分发，返回True，否则返回False。
        """
        return self._assigned
        
    def assignTo(self, robot_controller):
        """
        将该任务分配到索引为robot_idx的机器人。调用该函数会让任务的状态变为STATE_NOT_SCHEDULED，已分发但尚未调度。
        :param robot_id: 所分配给的机器人的ID。
        """
        self._assigned_robot_controller = robot_controller
        self._assigned = True
        
    def getAssignedRobotController(self):
        """
        获取本复合任务被分发给的机器人控制器。
        :return: 本复合任务被分发给的机器人控制器（RobotController对象）。
        """
        return self._assigned_robot_controller
        
    def __lt__(self, other):
        """
        本任务是否小于任务other。优先级高的任务大。
        :param other: 将self与other这两个任务比较大小。
        """
        return self.getNextUncompletedTask() < other.getNextUncompletedTask()

    def __gt__(self, other):
        """
        本任务是否大于任务other。优先级高的任务大。
        :param other: 将self与other这两个任务比较大小。
        """
        return self.getNextUncompletedTask() > other.getNextUncompletedTask()

    def __le__(self, other):
        """
        本任务是否小于等于任务other。优先级高的任务大。
        :param other: 将self与other这两个任务比较大小。
        """
        return self.getNextUncompletedTask() <= other.getNextUncompletedTask()

    def __ge__(self, other):
        """
        本任务是否大于等于任务other。优先级高的任务大。
        :param other: 将self与other这两个任务比较大小。
        """
        return self.getNextUncompletedTask() >= other.getNextUncompletedTask()

    def __eq__(self, other):
        """
        本任务是否等于任务other。
        :param other: 将self与other这两个任务比较。
        """
        return self.getNextUncompletedTask() == other.getNextUncompletedTask()

    def __ne__(self, other):
        """
        本任务是否不等于任务other。
        :param other: 将self与other这两个任务比较。
        """
        return self.getNextUncompletedTask() != other.getNextUncompletedTask()
        

if __name__ == '__main__':
    ct0 = CompositeTask()
    ct0.add(t0)
    ct0.add(t1)
    